package com.forlgb.powercloud.base.client.source.config;

import com.forlgb.powercloud.base.client.source.entity.SysRolePermission;
import com.forlgb.powercloud.base.client.source.mapper.SysPermissionMapper;
import com.forlgb.powercloud.base.client.source.service.impl.RedisServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static com.forlgb.powercloud.base.client.source.constant.Constants.SYS_ROLE_PERMISSION_KEY;
import static com.forlgb.powercloud.base.client.source.constant.Constants.SYS_ROLE_PERMISSION_MAP;


@Component
public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource {

    @Resource
    private SysPermissionMapper sysPermissionMapper;
    @Autowired
    private RedisServiceImpl redisService;

    /**
     * 每一个资源所需要的角色 Collection<ConfigAttribute>决策器会用到
     */
    private static HashMap<String, Collection<ConfigAttribute>> map =null;

    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        //暂时存内存中，之后要改到redis中
        if (CollectionUtils.isEmpty(map)) {
            loadResourceDefine();
        }
        //object 中包含用户请求的request 信息
        HttpServletRequest request = ((FilterInvocation) o).getHttpRequest();
        for (Iterator<String> it = map.keySet().iterator(); it.hasNext();) {
            String url = it.next();
            if (new AntPathRequestMatcher( url ).matches( request )) {
                return map.get( url );
            }
        }

        return null;
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }

    /**
     * 初始化 所有资源 对应的角色
     */
    public void loadResourceDefine() {
        map = new HashMap<>(16);
        map = redisService.getHashMap(SYS_ROLE_PERMISSION_MAP);
        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(map)){
            List<SysRolePermission> sysRolePermissions;
            //权限资源 和 角色对应的表  也就是 角色权限 中间表
            sysRolePermissions = redisService.getList(SYS_ROLE_PERMISSION_KEY);
            if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(sysRolePermissions)){
                sysRolePermissions = sysPermissionMapper.getSysRolePermissionByRoleId();
                redisService.setList(SYS_ROLE_PERMISSION_KEY, sysRolePermissions);
            }

            //某个资源 可以被哪些角色访问
            for (SysRolePermission sysRolePermission : sysRolePermissions) {

                String url = sysRolePermission.getUrl();
                String roleName = sysRolePermission.getRoleName();
                //这个SecurityConfig,
                ConfigAttribute role = new SecurityConfig(roleName);

                if(map.containsKey(url)){
                    map.get(url).add(role);
                }else{
                    List<ConfigAttribute> list =  new ArrayList<>();
                    list.add( role );
                    map.put( url , list );
                }
            }
            redisService.setHashMap(SYS_ROLE_PERMISSION_MAP, map);
        }
    }
}
